﻿using Microsoft.SharePoint;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;

namespace WindStyle.SPEntity
{
    public static class ConverterProvider
    {
        static readonly Dictionary<Type, Type> _fieldValueConverterTypes = new Dictionary<Type, Type>();
        static readonly Dictionary<Type, Type> _propertyConverterTypes = new Dictionary<Type, Type>();
        static readonly Dictionary<Type, Converters.IValueConverter> _converterInstances = new Dictionary<Type, Converters.IValueConverter>();

        static ConverterProvider()
        {
            Register(typeof(double), typeof(Converters.DoubleConverter));
            Register(typeof(string), typeof(Converters.StringConverter));
            Register(typeof(SPFieldUrlValue), typeof(Converters.SPFieldUrlValueConverter));
            Register(typeof(SPFieldMultiChoiceValue), typeof(Converters.SPFieldMultiChoiceValueConverter));
            Register(typeof(SPFieldLookupValue), typeof(Converters.SPFieldLookupValueConverter));
            Register(typeof(SPFieldLookupValueCollection), typeof(Converters.SPFieldLookupValueCollectionConverter));
            Register(typeof(SPFieldUserValue), typeof(Converters.SPFieldLookupValueConverter));
            Register(typeof(SPFieldUserValueCollection), typeof(Converters.SPFieldLookupValueCollectionConverter));
        }

        static void Register(Type type, Type converterType)
        {
            if (!_fieldValueConverterTypes.ContainsKey(type))
                _fieldValueConverterTypes.Add(type, converterType);
        }

        static bool IsTypeManaged(Type type, Dictionary<Type, Type> types)
        {
            if (type != null)
            {
                if (types.Any(t => t.Key.IsAssignableFrom(type)))
                    return true;
                else
                {
                    var converterAttribute = type.GetCustomAttributes(typeof(Attributes.ConverterAttribute), true);
                    if (converterAttribute.Any())
                    {
                        types.Add(type, (converterAttribute.First() as Attributes.ConverterAttribute).ConverterType);
                        return true;
                    }
                }
            }
            return false;
        }

        public static Converters.IValueConverter GetConverterForField(Type type)
        {
            return GetConverterForField(type, _fieldValueConverterTypes);
        }

        public static Converters.IValueConverter GetConverterForProperty(Type type)
        {
            return GetConverterForField(type, _propertyConverterTypes);
        }

        static Converters.IValueConverter GetConverterForField(Type type, Dictionary<Type, Type> types)
        {
            if (IsTypeManaged(type, types))
            {
                var converterType = types.FirstOrDefault(t => t.Key == type).Value;
                if (converterType == null)
                    converterType = types.First(t => t.Key.IsAssignableFrom(type)).Value;
                Converters.IValueConverter converter;
                if (_converterInstances.ContainsKey(type))
                    converter = _converterInstances[type];
                else
                {
                    converter = Activator.CreateInstance(converterType) as Converters.IValueConverter;
                    _converterInstances.Add(type, converter);
                }
                return converter;
            }
            else
                return null;
        }
    }
}
